package com.zhike.service.messages.impl;

import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zhike.common.dto.MsgBodyRoot;
import com.zhike.common.dto.OfflineMsgDTO;
import com.zhike.common.dto.RevokedDTO;
import com.zhike.common.enums.ResultCode;
import com.zhike.common.exception.ZkimException;
import com.zhike.common.model.Device;
import com.zhike.common.repository.HistoryMessage;
import com.zhike.mapper.messages.MessagesMapper;
import com.zhike.mobileimsdk.server.processor.OnlineProcessor;
import com.zhike.mobileimsdk.server.protocal.Protocal;
import com.zhike.service.group.IGroupService;
import com.zhike.service.im.manager.ChatManager4Group;
import com.zhike.service.im.manager.MessageRecordManager;
import com.zhike.service.messages.IHistoryMessageRepository;
import com.zhike.service.messages.IMessagesService;
import com.zhike.utils.MessageHelper;
import com.zhike.utils.MessageHelper.SendResultObserver;
import com.zhike.utils.manager.UsersStatusManager;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class MessagesServiceImpl implements IMessagesService {

  @Resource
  private MessagesMapper messagesMapper;

  @Autowired
  private IHistoryMessageRepository historyMessageRepository;

  @Autowired
  private IGroupService groupService;

  @Resource
  private MessageRecordManager messageRecordManager;

  @Autowired
  private UsersStatusManager usersStatusManager;

  @Autowired
  private MessageHelper messageHelper;

  @Autowired
  private ChatManager4Group chatManager4Group;

  @Override
  public Integer queryOfflineHistoryCountByFingerPrint(String fingerPrint) {
    return messagesMapper.queryOfflineHistoryCountByFingerPrint(fingerPrint);
  }

  @Override
  public Boolean insertOfflineHistoryData(String fromUid, String toUid, String msgType, String message,
      String messageContent2, String historyTime2, Integer chatType, String groupId, String parentFp) {
    return messagesMapper.insertOfflineHistoryData(fromUid, toUid, msgType, message, messageContent2,
        historyTime2, chatType, groupId, parentFp);
  }

  @Override
  public List<OfflineMsgDTO> getOfflineFriendsMessages(Boolean isIncludeFingerPring, String fromUserUid,
      String userUid) {
    return messagesMapper.getOfflineFriendsMessages(isIncludeFingerPring, fromUserUid, userUid);
  }

  @Override
  public Boolean deleteOfflineHistoryByFriendUserUid(String userUid, String fromUserUid) {
    return messagesMapper.deleteOfflineHistoryByFriendUserUid(userUid, fromUserUid) > 0;
  }

  public Boolean revokeMessage(String uid, RevokedDTO dto) {

    HistoryMessage hm = historyMessageRepository.findHistoryMessageByFp(dto.getFp());
    if (hm == null) {
      throw new ZkimException(ResultCode.MSG_NOTFOUND);
    }

    // 权限校验
    if (StringUtils.isNotBlank(dto.getGroupId())) {
      if (!groupService.isGroupOwner(dto.getGroupId(), uid) && !groupService.isGroupAdmin(dto.getGroupId(), uid)) {
        // 成员 只能撤销自己发的消息
        if (!uid.equals(hm.getSenderUid())) {
          throw new ZkimException(ResultCode.MSG_REVOKE_NORIGHT);
        }
      }

      // 管理员只能撤销成员的消息
      if (groupService.isGroupAdmin(dto.getGroupId(), uid)) {
        if (groupService.isGroupAdmin(dto.getGroupId(), hm.getSenderUid())
            && groupService.isGroupOwner(dto.getGroupId(), hm.getSenderUid())) {
          throw new ZkimException(ResultCode.MSG_REVOKE_NORIGHT);
        }
      }
    }

    if (!groupService.isGroupOwner(dto.getGroupId(), uid)) {
      // 时间校验 超过2分钟不允许撤回 (群主不用校验)
      long cha = DateUtil.between(hm.getTimestamp(), new Date(), DateUnit.MINUTE);
      if (cha > 2) {
        throw new ZkimException(ResultCode.MSG_REVOKE_TIMEOUT);
      }
    }

    // 更新消息的状态为撤销
    return historyMessageRepository.revokeMessage(dto.getFp());
  }

  private AtomicInteger count = new AtomicInteger(0);

  @Override
  public void sendMessageToClient(String deviceId, String fp, MsgBodyRoot p) throws Exception {
    if (usersStatusManager.isOnline(deviceId)) {
      SendResultObserver sendResultObserver = new SendResultObserver() {
        @Override
        public void update(boolean code,
            com.zhike.mobileimsdk.server.protocal.Protocal p) {
          count.incrementAndGet();
          log.info("成功发送消息数量: {}", count.get());
        }
      };
      messageHelper.sendMessage(deviceId, p.getM(), true,
          3, sendResultObserver);
    }
    messageRecordManager.colectChattingMsgAsync(deviceId, JSONUtil.toJsonStr(p), 0, fp);

  }

  @Override
  public void sendMessageToGroup(String fp, String dataJson) {
    chatManager4Group.processMT44_OF_GROUP$CHAT$MSG_A$TO$SERVER(fp, dataJson);
  }

}
